from psd_tools import PSDImage
from psd_tools.constants import ChannelID




 
from wand.image import Image  as WsImage
import photoshop.api as ps


from pathlib import Path
import numpy as np

import bisect

import time 
from PIL import Image
import numpy as np
from sklearn.neighbors import KDTree
for i in range(2,6):
    print(i)

from photoshop import Session
#with WsImage(filename = "./30-40-test-1.png") as img:
#    img.read(filename = "./30-40-test-2.png" )
# #   img.read(filename = "./30-40-test-1.png" )
#    img.save(filename = "test.psd")



img_test = Image.new('RGBA', (1000, 1000), (0,0,0,0))
img_test.save("c://temp//without_pix.png")


#app = ps.Application()
#app.load("80-80-呆呆的呆呆517.psd")

 

colors = np.array([[255,233,7],[255,233,7],[5,233,7],[255,23,7],[255,213,7]]) 

tree = KDTree(colors)
target_color = np.array([4,222,8])
dist, ind = tree.query([target_color], k = 1)


print(colors[ind[0]])
#index  界定的范围  要找的index数组长度
def GetNearIndex(curr_idx, size,lenth):
    left = size/2
    right = size/2
    left_idx = curr_idx
    right_idx = curr_idx
    while left > 0 and left_idx > 0 :
        left = left -1
        left_idx = left_idx - 1
    while right_idx < lenth  and right + left > 0:
        right_idx = right_idx + 1
        right = right - 1
    return  left_idx, right_idx 
        


num = GetNearIndex(1123, 10,  1125)



def GetNearst(element, pixel_index):
    # Use binary search to find index of nearest value in B_sorted
    idx = bisect.bisect_left(pixel_index, element, lo=0, hi=len(pixel_index))
    if idx == 0:
        print(pixel_index[idx])
    elif idx == len(pixel_index):
        print(pixel_index[-1])
    else:
        # Compare two closest values in B_sorted
        if element - pixel_index[idx-1] < pixel_index[idx] - element:
            print(pixel_index[idx-1])
        else:
            print(pixel_index[idx])


TheArray = [1,2,58,9999,5675,4,66666,434,464646,34,4434,466,44,2,35,564,232]
value = sorted(TheArray)
GetNearst(40, value)





#with WsImage(filename = "./45-60-50158-995-1.png") as img:
#    img.read(filename = "./45-60-50158-995-2.png" )
#    img.save(filename = "test.psd")


#from psd_tools import PSDImage

## Open PSD files
#file1 = PSDImage.open('file1.psd')
#file2 = PSDImage.open('file2.psd')

## Get the layers of the PSD files
#layers1 = file1.layers
#layers2 = file2.layers

## Merge the layers of both PSD files
#merged_layers = layers1 + layers2

## Create a new PSD file with the merged layers
#merged_psd = PSDImage(layers=merged_layers, size=file1.size)

## Save the new PSD file
#merged_psd.save('merged.psd')



#import xml.etree.ElementTree as ET

# Open the SVG files
#svg1 = ET.parse('30-40-ganli1985-1.svg').getroot()
#svg2 = ET.parse('30-40-ganli1985-2.svg').getroot()

# Create a new SVG element
#merged_svg = ET.Element('svg')

# Add the attributes from one of the original SVGs to the merged SVG
#merged_svg.attrib = svg1.attrib

# Add the contents of each SVG to the merged SVG
#for elem in svg1:
#    merged_svg.append(elem)
#for elem in svg2:
 #   merged_svg.append(elem)

# Write the merged SVG to a file
#ET.ElementTree(merged_svg).write('merged.svg')

skin_lines  =  []
ground_lines  =  []
mouth_lines  =  []





ground_fp = Path('background.txt')
with ground_fp.open() as fp:
     cnt = 0
     for line in fp:
         if cnt == 0:
             cnt = cnt +1
             continue
         ground_lines.append(line.rstrip())



skin_fp = Path('skin.txt')
with skin_fp.open() as fp:
     cnt = 0
     for line in fp:
         if cnt == 0:
             cnt = cnt +1
             continue
         skin_lines.append(line.rstrip())



mouth_fp = Path('mouth.txt')

with mouth_fp.open() as fp:

     cnt = 0
     for line in fp:
         if cnt == 0:
             cnt = cnt +1
             continue
         mouth_lines.append(line.rstrip())



#@
g_path_file = '60-35-大哪吒和金刚葫芦娃+卡▲.psd'

#def change_visible():
#    psd_path = g_path_file
#    psd = PSDImage.open(psd_path)  # 打开psd对象
#    for index, layer in enumerate(psd.descendants()):
#        layer_name = layer.name  # 图层名称
        
#        layer.visible = True
#    psd.save(psd_path)  # 保存


#change_visible
psd = PSDImage.open(g_path_file)


ground_max = 9999
ground_min = -1


ground_dict = {}
for i in range(0, len(ground_lines)):

    ground_lines[i] = list(map(int, ground_lines[i].split(",")))
    #ground_lines[i] = tuple(ground_lines[i])
    
    sum =   ground_lines[i][0]**2 + ground_lines[i][1]**2 + ground_lines[i][2]**2
    ground_max =max(sum,ground_max)
    ground_min =min(sum,ground_min)
    if sum in ground_dict.keys():
        ground_dict[sum].append(tuple(ground_lines[i]))
    else:
        ground_dict.setdefault(sum, [])
        ground_dict[sum].append(tuple(ground_lines[i]))

ground_tree = KDTree(ground_lines)




mouth_dict = {}
for i in range(0, len(mouth_lines)):
    mouth_lines[i] = list(map(int, mouth_lines[i].split(",")))
    #mouth_lines[i] = tuple(mouth_lines[i])
    sum =   mouth_lines[i][0] + mouth_lines[i][1] + mouth_lines[i][2]
    ground_max =max(sum,ground_max)
    ground_min =min(sum,ground_min)
    if sum in mouth_dict.keys():
        mouth_dict[sum].append(tuple(mouth_lines[i]))
    else:
        mouth_dict.setdefault(sum, [])
        mouth_dict[sum].append(tuple(mouth_lines[i]))

mouth_tree = KDTree(mouth_lines)
skin_dict = {}
for i in range(0, len(skin_lines) ):
    skin_lines[i] = list(map(int, skin_lines[i].split(",")))
    #skin_lines[i] = tuple(skin_lines[i])
    sum =   skin_lines[i][0] + skin_lines[i][1] + skin_lines[i][2]
    ground_max =max(sum,ground_max)
    ground_min =min(sum,ground_min)
    if sum in skin_dict.keys():
        skin_dict[sum].append(tuple(skin_lines[i]))
    else:
        skin_dict.setdefault(sum, [])
        skin_dict[sum].append(tuple(skin_lines[i]))
#psd.composite().save('example.png')

skin_tree = KDTree(skin_lines)




def GetNearst(element, pixel_index):
    # Use binary search to find index of nearest value in B_sorted
    idx = bisect.bisect_left(pixel_index, element)
    if idx == 0:
        #print(pixel_index[idx])
        return pixel_index[idx],idx
    elif idx == len(pixel_index):
        return pixel_index[-1], -1
    else:
        # Compare two closest values in B_sorted
        if element - pixel_index[idx-1] < pixel_index[idx] - element:
            return pixel_index[idx-1] , idx -1
        else:
            return pixel_index[idx], idx








def copy_to_whole_image(curr_layer, w, h):
    x_begin = curr_layer.bbox[0]
    y_begin = curr_layer.bbox[1]
    x_end = curr_layer.width + x_begin
    y_end = curr_layer.height + y_begin
    if w == x_end and h == y_end:
        return  curr_layer.topil()

    curr_img = Image.new('RGBA', (w, h), (0,0,0,0))
    image_from_layer = curr_layer.topil()
    for i in  range(0, curr_img.width):
        if i <= x_begin or i >= x_end:
            continue
        for j in range ( 0 , curr_img.height):
            if j <= y_begin or j>= y_end:
                continue
            pix_x = i - x_begin
            pix_y = j - y_begin
            pix = image_from_layer.getpixel( (pix_x , pix_y ) )
            curr_img.putpixel((i ,j),  pix  );
    #curr_img.save("test_layer.png")
    return curr_img



def proc_layer(curr_layer, curr_tree, curr_dict, curr_layer_num,  png_index):
    src_size = curr_layer.parent.size
    image = copy_to_whole_image(curr_layer, src_size[0], src_size[1])
    
    for w in range(0,image.width ):
        for h in range (0 , image.height):
             if w == 410 and h == 302:
                 print(333)
             pix = image.getpixel((w,h))
             if pix[3] == 0:
                 continue
             target_color = np.array([pix[0], pix[1], pix[2]])
             dist, ind = curr_tree.query([target_color], k = 1)
             k_pix = curr_dict[ind[0][0]]
             image.putpixel((w, h), tuple(k_pix))
    file_name = g_path_file[:-4]
    image.save(file_name +"-" + str(png_index) + ".png")


def zero_psd(curr_layer):
    image = curr_layer.topil()
    
    for w in range(0,curr_layer.width ):
        for h in range (0 , curr_layer.height):
            image.putpixel((w, h), (0,0,0,0))


def proc_psd(psd):
    curr_layer = 0

    for layer in psd:
        
        print(layer)
        #proc_watch(layer)


        print(layer.has_mask())
        image = layer.topil()
        print(image.mode)
        red = layer.topil(ChannelID.CHANNEL_0)
        green = layer.topil(ChannelID.CHANNEL_1)
        blue = layer.topil(ChannelID.CHANNEL_2)
        if curr_layer == 0:
            #zero_psd(layer)

            curr_layer = curr_layer + 1
            #continue
            proc_layer(layer, ground_tree, ground_lines,  curr_layer, 1)
        elif curr_layer == 1:
            #zero_psd(layer)

            curr_layer = curr_layer + 1
            #continue
            proc_layer(layer, skin_tree, skin_lines,  curr_layer, 2)
            proc_layer(layer, ground_tree, ground_lines,  curr_layer, 20)
        elif curr_layer == 2:
            curr_layer = curr_layer + 1
            proc_layer(layer, mouth_tree, mouth_lines, curr_layer, 3)
        elif curr_layer == 3:
            curr_layer = curr_layer + 1
            proc_layer(layer, ground_tree, ground_lines, curr_layer, 4)
    psd.save("watch.psd")


def proc_watch(curr_layer):
    image = curr_layer.topil()

    for w in range(0,curr_layer.width ):
    #print(w)
    
        for h in range (0 , curr_layer.height):
            min = 999999
            pix = image.getpixel((w,h))
            fill_pix = []
            #print(ground_lines)
            for color_ in ground_lines:

                curr_pix_s = abs(pix[0] - color_[0])**2 + abs(pix[1] - color_[1])**2 + abs(pix[2] - color_[2])**2
                if curr_pix_s < min:
                    fill_pix = color_
                    min = curr_pix_s
            
            if len(fill_pix) > 0:
                image.putpixel((w, h), tuple(fill_pix))
                currs = image.getpixel((w,h))
    image.save('watch.png')

def proc_psds(psd):
    curr_layer = 0
    for layer in psd:
        
        print(layer)
        #proc_watch(layer)
        print(layer.has_mask())
        image = layer.topil()
        red = layer.topil(ChannelID.CHANNEL_0)
        green = layer.topil(ChannelID.CHANNEL_1)
        blue = layer.topil(ChannelID.CHANNEL_2)
        print(red.size)
        print(image.getpixel((10, 10)))
        print(red.getpixel((10, 10)))
    
        if curr_layer == 0:
            curr_layer = curr_layer + 1
            curr_keys =  ground_dict.keys()
            sorted_key = sorted(curr_keys)
            print(sorted_key)
            for w in range(0,layer.width ):
                #print(w)
                
                for h in range (0 , layer.height):
                    if w == 459 and h == 234:
                        print(444)
                    pix = image.getpixel((w,h))
                    if pix[3] == 0:
                        continue


                    
                    target_color = np.array([pix[0], pix[1], pix[2]])
                    dist, ind = ground_tree.query([target_color], k = 1)
                    vallue = ind[0][0]
                    k_pix = ground_lines[ind[0][0]]
                    image.putpixel((w, h), tuple(k_pix))
                    continue

                    pix_sum = pix[0] ** 2 + pix[1] ** 2 + pix[2] ** 2

                    near_pix_index = GetNearst(pix_sum, sorted_key)

                    first_paint_color = ground_dict[ sorted_key[near_pix_index[1]]]

                    index_range = GetNearIndex(near_pix_index[1], 60, len(sorted_key))

                    min_distance = abs(first_paint_color[0][0] - pix[0]) **2  +  abs(first_paint_color[0][1] - pix[1]) **2  +  abs(first_paint_color[0][2] - pix[2]) **2   
                    fill_pix = first_paint_color[0]
                    for idx in range(index_range[0],  index_range[1] ):
                        curr_paint_color_list = ground_dict[ sorted_key[idx]]
                        for curr_paint_color in curr_paint_color_list:
                            curr_min_distance = abs(curr_paint_color[0] - pix[0]) **2  +  abs(curr_paint_color[1] - pix[1]) **2  +  abs(curr_paint_color[2] - pix[2]) **2   
                            if curr_min_distance < min_distance:
                                min_distance = curr_min_distance
                                fill_pix = curr_paint_color

                    #fill_pix =[]
                    #first_paint_color = ground_dict[near_pix_index[0]]
                    #curr_min_distance = abs(first_paint_color[0][0] - pix[0]) **2  +  abs(first_paint_color[0][1] - pix[1]) **2  +  abs(first_paint_color[0][2] - pix[2]) **2   
                    #fill_pix = first_paint_color
                    #if near_pix_index[1] - 1 > 0:
                    #    pre_near_pix_index = sorted_key[near_pix_index[1] - 1]
                    #    pre_paint_color = ground_dict[pre_near_pix_index]
                    #    pre_distance = abs(pre_paint_color[0][0] - pix[0]) **2  +  abs(pre_paint_color[0][1] - pix[1]) **2  +  abs(pre_paint_color[0][2] - pix[2]) **2 
                    #    if pre_distance < curr_min_distance:
                    #        fill_pix = pre_paint_color
                    #        curr_min_distance = pre_distance
                    #if near_pix_index[1] + 1 < len(sorted_key):
                    #    next_near_pix_index = sorted_key[near_pix_index[1] - 1]
                    #    next_paint_color = ground_dict[next_near_pix_index]
                    #    next_distance = abs(next_paint_color[0][0] - pix[0]) **2  +  abs(next_paint_color[0][1] - pix[1]) **2  +  abs(next_paint_color[0][2] - pix[2]) **2 
                    #    if next_distance < curr_min_distance:
                    #        fill_pix = next_paint_color
                    #        curr_min_distance = next_distance
                    if len(fill_pix) > 0:
                        image.putpixel((w, h), fill_pix)
                        currs = image.getpixel((w,h))
                        #print(currs)
 

                   
        elif curr_layer == 1:
            curr_layer = curr_layer + 1
            curr_keys =  ground_dict.keys()
            sorted_key = sorted(curr_keys)

            for w in range(0,layer.width ):
                #print(w)
                
                for h in range (0 , layer.height):
                    
                    pix = image.getpixel((w,h))
                    pix_sum = pix[0] + pix[1] + pix[2]

                    near_pix_index = GetNearst(pix_sum, sorted_key)

                    fill_pix =[]
                    color_list = ground_dict[near_pix_index]
                    min = 999
                    if w == 78 and h == 507:
                        print(444)
                    for color_ in color_list:
                        curr_pix_s = abs(pix[0] - color_[0])**2 + abs(pix[1] - color_[1])**2 + abs(pix[2] - color_[2])**2
                        if curr_pix_s < min:
                            fill_pix = color_list
                    if len(fill_pix) > 0:
                        image.putpixel((w, h), fill_pix[0])
                        currs = image.getpixel((w,h))
        elif curr_layer == 2:
            curr_layer = curr_layer + 1
            curr_keys =  ground_dict.keys()
            sorted_key = sorted(curr_keys)

            for w in range(0,layer.width ):
                #print(w)
                
                for h in range (0 , layer.height):
                    
                    pix = image.getpixel((w,h))
                    pix_sum = pix[0] + pix[1] + pix[2]

                    near_pix_index = GetNearst(pix_sum, sorted_key)

                    fill_pix =[]
                    color_list = ground_dict[near_pix_index]
                    min = 999
                    for color_ in color_list:
                        curr_pix_s = abs(pix[0] - color_[0])**2 + abs(pix[1] - color_[1])**2 + abs(pix[2] - color_[2])**2
                        if curr_pix_s < min:
                            fill_pix = color_list
                    if len(fill_pix) > 0:
                        image.putpixel((w, h), fill_pix[0])
                        currs = image.getpixel((w,h))
        if curr_layer == 3:
            curr_layer = curr_layer + 1
            curr_keys =  ground_dict.keys()
            sorted_key = sorted(curr_keys)

            for w in range(0,layer.width ):
                #print(w)
                
                for h in range (0 , layer.height):
                    
                    pix = image.getpixel((w,h))
                    pix_sum = pix[0] + pix[1] + pix[2]

                    near_pix_index = GetNearst(pix_sum, sorted_key)

                    fill_pix =[]
                    color_list = ground_dict[near_pix_index]
                    min = 999
                    for color_ in color_list:
                        curr_pix_s = abs(pix[0] - color_[0])**2 + abs(pix[1] - color_[1])**2 + abs(pix[2] - color_[2])**2
                        if curr_pix_s < min:
                            fill_pix = color_list
                    if len(fill_pix) > 0:
                        image.putpixel((w, h), fill_pix[0])
                        currs = image.getpixel((w,h))
      
 

        image.save('80-60-你猜fhxnccgjbcjb++.png')
        #merged_psd = PSDImage(layers=layer, size=psd.size)
        #width1, height1 = psd.size
        #merged_psd = PSDImage.new(width = width1, height = height1)
       # merged_psd.add(layer)
    #layer_image.save('%s.png' % layer.name)

proc_psd(psd)